package org.szy.plugin.dev.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.util.UpdateEntity;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.ProxyComponent;
import org.szy.core.common.exception.BaseException;
import org.szy.core.common.param.CommonMoveParam;
import org.szy.core.common.param.CommonStatusParam;
import org.szy.core.common.service.impl.BaseServiceImpl;
import org.szy.core.common.uilts.TreeBuildFactory;
import org.szy.plugin.dev.entity.DevDict;
import org.szy.plugin.dev.mapper.DevDictMapper;
import org.szy.plugin.dev.param.DevDictQueryParam;
import org.szy.plugin.dev.pojo.DevDictTree;
import org.szy.plugin.dev.service.DevDictService;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.szy.plugin.dev.entity.table.DevDictTableDef.DEV_DICT;

/**
 * 开发_字典Service接口实现类
 *
 * @author wangbuhao
 * @since 2023-06-20 16:05:55
 **/
@ProxyComponent
public class DevDictServiceImpl extends BaseServiceImpl<DevDictMapper, DevDict> implements DevDictService {

    @Inject
    private DevDictMapper devDictMapper;

    @Override
    public QueryWrapper qwByQuery(DevDictQueryParam param) {
        QueryWrapper qw = new QueryWrapper();
        if (StrUtil.isNotEmpty(param.getColumnField())) {
            qw.select(param.getColumnField().split(","));
        }
        if (StrUtil.isNotEmpty(param.getCategory())) qw.and(DEV_DICT.CATEGORY.eq(param.getCategory()));
        if (StrUtil.isNotEmpty(param.getLabel())) qw.and(DEV_DICT.LABEL.eq(param.getLabel()));
        if (StrUtil.isNotEmpty(param.getCode())) qw.and(DEV_DICT.CODE.eq(param.getCode()));
        if (StrUtil.isNotEmpty(param.getCodeLike())) qw.and(DEV_DICT.CODE.like(param.getCodeLike()));
        if (param.getGtLevel() != null) qw.and(DEV_DICT.LEVEL.gt(param.getGtLevel()));
        if (param.getLtLevel() != null) qw.and(DEV_DICT.LEVEL.lt(param.getLtLevel()));
        if (param.getStatus() != null) qw.and(DEV_DICT.STATUS.eq(param.getStatus()));
        qw.orderBy(DEV_DICT.SORT.asc());
        return qw;
    }

    @Override
    public List<DevDict> list(DevDictQueryParam param) {
        QueryWrapper queryWrapper = qwByQuery(param);
        return this.list(queryWrapper);
    }


    @Override
    public boolean add(DevDict entity) {
        boolean exists = exists(DEV_DICT.CODE.eq(entity.getCode()));
        if (exists) throw new BaseException("数据字典代码已存在");
        entity.setPids(createNewPids(entity.getPid()));
        if (entity.getSort() == null) {
            long count = count();
            entity.setSort(Convert.toInt(count, 0) + 1);
        }
        String[] split = entity.getPids().split(",");
        entity.setLevel(split.length);
        return save(entity);
    }

    @Override
    public boolean edit(DevDict entity) {
        boolean exists = exists(DEV_DICT.CODE.eq(entity.getCode()).and(DEV_DICT.ID.ne(entity.getId())));
        if (exists) throw new BaseException("数据字典代码已存在");
        if (Objects.equals(entity.getId(), entity.getPid()))
            throw new BaseException("数据字典不能选择自己");
        entity.setPids(createNewPids(entity.getPid()));
        String[] split = entity.getPids().split(",");
        entity.setLevel(split.length);
        return updateById(entity);
    }

    @Override
    public boolean deleteById(Long id) {
        return remove(DEV_DICT.ID.eq(id).or(DEV_DICT.PIDS.like(id)));
    }

    @Override
    public List<DevDictTree> buildTrees(List<DevDict> list) {
        int level = list.stream().mapToInt(DevDict::getLevel).min().orElse(0);
        Long pid = 0L;
        if (level > 0) {
            List<DevDict> dicts = list.stream().filter(item -> Objects.equals(item.getLevel(), level)).collect(Collectors.toList());
            if (dicts.size() > 0) pid = dicts.get(0).getPid();
        }
        List<DevDictTree> lists = BeanUtil.copyToList(list, DevDictTree.class);
        List<DevDictTree> trees = new TreeBuildFactory<DevDictTree>(pid).doTreeBuild(lists);
        return trees;
    }

    @Override
    public List<DevDictTree> treeByCode(DevDictQueryParam param) {
        QueryWrapper qw = new QueryWrapper();
        qw.select("id", "pid", "name", "code", "level", "value").and(DEV_DICT.STATUS.eq(1));
        qw.and(i -> {
            i.and(DEV_DICT.CODE.eq(param.getCode()));
            i.or(DEV_DICT.CODE.like(param.getCode() + "_"));
        });
        List<DevDict> list = list(qw);
        if (list.isEmpty()) return new ArrayList<>(1);
        return buildTrees(list);
    }

    @Override
    public boolean move(CommonMoveParam param) {
        DevDict entity = this.getById(param.getId(), "id,pid,sort");
        QueryWrapper qw = new QueryWrapper().limit(1);
        qw.select("id,pid,sort").and(DEV_DICT.PID.eq(entity.getPid()));
        List<DevDict> list;
        switch (param.getType()) {
            // 上移
            case "1":
                qw.and(DEV_DICT.SORT.lt(entity.getSort())).orderBy(DEV_DICT.SORT.desc());
                list = list(qw);
                if (list.size() == 0) throw new BaseException("没有可交换的上级数据字典");
                break;
            // 下移
            case "2":
                qw.and(DEV_DICT.SORT.gt(entity.getSort())).orderBy(DEV_DICT.SORT.asc());
                list = list(qw);
                if (list.size() == 0) throw new BaseException("没有可交换的下级数据字典");
                break;
            default:
                return false;
        }
        DevDict moveEntity = list.get(0);

        DevDict moveE = UpdateEntity.of(DevDict.class, entity.getId());
        moveE.setSort(moveEntity.getSort());
        devDictMapper.update(moveE);

        DevDict moveE2 = UpdateEntity.of(DevDict.class, moveEntity.getId());
        moveE2.setSort(entity.getSort());
        devDictMapper.update(moveE2);

        return true;
    }

    @Override
    public boolean modifyStatus(CommonStatusParam param) {
        DevDict entity = UpdateEntity.of(DevDict.class, param.getId());
        entity.setStatus(param.getStatus());
        return devDictMapper.update(entity) > 0;
    }


}
